unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, UMono, UMonoIntf, UMonoRTTIInv, UScriptClass, UVarMono, StdCtrls, DB,
  DBClient, Grids, DBGrids;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    ClientDataSet1: TClientDataSet;
    ClientDataSet1COl1: TStringField;
    ClientDataSet1COL2: TIntegerField;
    ClientDataSet1COL3: TIntegerField;
    ClientDataSet1COLSUM: TIntegerField;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    FPlugin: variant;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  ClientDataSet1.CreateDataSet;

  FPlugin := VarMonoCreate(MonoJit.FindMonoClass('Mono4Delphi', 'MainClass'));
  FPlugin.InitPlugin(O2V(self));

  ClientDataSet1.DisableControls;
  try
    Randomize;
    for i := 0 to 9999 do
      ClientDataSet1.AppendRecord(['rec'+intToStr(i), Random(1000), Random(1000)]);
    ClientDataSet1.First;
  finally
    ClientDataSet1.EnableControls;
  end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown:= DebugHook <> 0;
  SetMonoPath('C:\Program Files\Mono-2.8.2\bin');
  InitMono;
end;

procedure myShowMessage(aValue: PMonoString); cdecl;
var
  sw: string;
begin
  sw := TMonoConvert.MonoStrToString(aValue);
  Dialogs.ShowMessage('MONO: '+sw);
end;

function getFieldAsInteger(aObj: pointer): integer; cdecl;
begin
  result := TField(aObj).AsInteger;
end;

procedure setFieldAsInteger(aObj: pointer; aValue: integer); cdecl;
begin
  TField(aObj).AsInteger := aValue;
end;

function myFieldByName(aObj: integer; aFieldName: PMonoString): pointer; cdecl;
var
  s: string;
  f: TField;
begin
  s := TMonoConvert.MonoStrToString(aFieldName);
  f := TDataset(aObj).FieldByName(s);
  result := pointer(f);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    MonoJit := TMonoJit.Create('v4.0.30319', OpenDialog1.FileName, '0', 0);

    MonoJit.AddInternalCall('Mono4Delphi','Dialogs','ShowMessage', @myShowMessage);
    MonoJit.AddInternalCall('Mono4Delphi','TProxyAnyIntf', 'DelphiInvoke', @DelphiRTTIInvoke);
    MonoJit.AddClassMap(TObject, 'Mono4Delphi.ITObject');
    MonoJit.AddClassMap(TComponent, 'Mono4Delphi.ITComponent');
    MonoJit.AddClassMap(TControl, 'Mono4Delphi.ITControl');
    MonoJit.AddClassMap(TForm, 'Mono4Delphi.ITForm');
    MonoJit.AddClassMap(TEdit, 'Mono4Delphi.ITEdit');
    MonoJit.AddClassMap(TButton, 'Mono4Delphi.ITButton');
    MonoJit.AddClassMap(TStrings, 'Mono4Delphi.ITStrings');
    MonoJit.AddClassMap(TMemo, 'Mono4Delphi.ITMemo');

    MonoJit.AddClassMap(TDataset, 'Mono4Delphi.ITDataset');
    MonoJit.AddClassMap(TField, 'Mono4Delphi.ITField');
    MonoJit.AddInternalCall('Mono4Delphi','MainClass', 'getFieldAsInteger', @getFieldAsInteger);
    MonoJit.AddInternalCall('Mono4Delphi','MainClass', 'setFieldAsInteger', @setFieldAsInteger);
    MonoJit.AddInternalCall('Mono4Delphi','MainClass', 'FieldByName', @myFieldByName);

    MonoJit.LoadAssembly;
  end;
end;

initialization
finalization
  MonoJit.Free;
end.
